package com.cskaoyan._04nio;

import org.apache.commons.io.FileUtils;
import org.junit.Test;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

/**
 * @description:
 * @author: 景天
 * @date: 2023/2/20 17:42
 **/

public class NIOTest {
    @Test
    public void myTest1() {
        // 创建缓冲区对象
        ByteBuffer buffer = ByteBuffer.allocate(10);
        System.out.println(buffer);
    }
    /*
    向buffer中放数据
     */
    @Test
    public void myTest2() {
        // 创建缓冲区对象
        ByteBuffer buffer = ByteBuffer.allocate(10);
        System.out.println(buffer);

        //// put(byte b)
        //buffer.put(((byte) 97));
        //// put(int index, byte b)
        //buffer.put(1, ((byte) 98));
        //System.out.println(buffer);

        // 批量操作
        buffer.put("abcd".getBytes());

        System.out.println(buffer);

    }


    /*
    从缓冲区中取数据
     */
    @Test
    public void myTest3() {
        // 创建缓冲区对象
        ByteBuffer buffer = ByteBuffer.allocate(10);
        System.out.println(buffer);
        // 批量操作
        buffer.put("abcd".getBytes());
        System.out.println(buffer);

        // 读写模式切换flip
        buffer.flip();
        System.out.println(buffer);

        //// 取数据 get方法
        //byte b = buffer.get();
        //System.out.println(b);
        //System.out.println(buffer);
        //
        //// get(int index)  读取指定索引处的字节。
        //// pos不变
        //byte b1 = buffer.get(1);
        //System.out.println(b1);
        //System.out.println(buffer);

        // 批量
        byte[] bytes = new byte[4];
        buffer.get(bytes);
        System.out.println(new String(bytes));
        System.out.println(buffer);

    }

    /*
    mark
     */
    @Test
    public void myTest4() {
        // 创建缓冲区对象
        ByteBuffer buffer = ByteBuffer.allocate(10);
        System.out.println(buffer);

        // 批量操作
        buffer.put("abcd".getBytes());
        // mark标记 记录position的值
        buffer.mark();

        buffer.put("ef".getBytes());
        System.out.println(buffer);

        // 通过reset方法 让pos变成刚才mark标记的位置
        buffer.reset();
        System.out.println(buffer);

    }

    /*
    循环读取
     */
    @Test
    public void myTest5() {
        // 创建缓冲区对象
        ByteBuffer buffer = ByteBuffer.allocate(10);
        System.out.println(buffer);

        // 批量操作
        buffer.put("abcd".getBytes());

        // flip
        buffer.flip();
        // 循环读取
        while (buffer.hasRemaining()) {
            byte b = buffer.get();
            System.out.println(b);
        }


        System.out.println(buffer);

    }

    /*
    获取文件通道的方式
     */
    @Test
    public void myTest6() throws IOException {
        // 举例
        FileChannel inChannel = new FileInputStream("a.mp4").getChannel();
        FileChannel outChannel = new FileOutputStream("a.mp4").getChannel();
        FileChannel rafIn = new RandomAccessFile("aa.mp4", "rw").getChannel();
    }

    /*
    文件内存映射
 */
    @Test
    public void myTest7() throws IOException {
        // 举例
        FileChannel channel =
                new RandomAccessFile("D:\\workspace2\\java48th\\a.txt", "rw").getChannel();

        // map方法进行映射
        MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, channel.size());

        //// 获取内存中的文件数据
        //byte[] bytes = new byte[4];
        //buffer.get(bytes);
        //System.out.println(new String(bytes));

        // 修改内存中文件的数据
        buffer.put(0, ((byte) 98));

    }

    @Test
    public void myTest8() throws IOException {
        // 举例
        FileChannel channel =
                new RandomAccessFile("D:\\workspace2\\java48th\\a.txt", "rw").getChannel();

        // map方法进行映射
        MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, channel.size());

        byte b = buffer.get();
        System.out.println(b);

    }

    @Test
    public void writeTest() throws IOException {

        // 创建通道
        FileChannel outChannel = new FileOutputStream("D:\\workspace2\\java48th\\c.txt").getChannel();
        // 创建缓冲区
        ByteBuffer buffer = ByteBuffer.allocate(64);
        // 向缓冲区写数据
        buffer.put("你不知道的事".getBytes());
        buffer.flip();
        // 向通道中写数据
        outChannel.write(buffer);
        outChannel.close();
    }

    @Test
    public void readTest() throws IOException{
        // 创建通道
        FileChannel inChannel = new FileInputStream("D:\\workspace2\\java48th\\c.txt").getChannel();
        // 创建缓冲区
        ByteBuffer buffer = ByteBuffer.allocate(64);
        // 将数据从通道读入到缓冲区
        inChannel.read(buffer);
        buffer.flip();
        // 把数据从缓冲区取出来
        byte[] bytes = new byte[1024];
        buffer.get(bytes, 0, buffer.limit());
        System.out.println(new String(bytes,0,buffer.limit()));
    }

    @Test
    public void scatterTest() throws IOException{
        // 分散测试
        // 创建一个通道
        FileChannel inChannel = new FileInputStream("D:\\workspace2\\java48th\\a.txt").getChannel();
        // 创建2个缓冲区
        ByteBuffer buffer1 = ByteBuffer.allocate(8);
        ByteBuffer buffer2 = ByteBuffer.allocate(8);
        ByteBuffer[] byteBuffer = {buffer1,buffer2};
        // 数据读入到缓冲区
        long readCount = inChannel.read(byteBuffer);
        System.out.println("readCount = " + readCount);
        System.out.println("buffer1.capacity() = " + buffer1.capacity()+ " position = " + buffer1.position());
        System.out.println("buffer2.capacity() = " + buffer2.capacity()+ " position = " + buffer2.position());
    }


    @Test
    public void gatherTest() throws IOException{
        // 聚集测试
        // 创建1个通道
        FileChannel outChannel = new FileOutputStream("D:\\workspace2\\java48th\\b.txt").getChannel();
        // 创建2个缓冲区
        ByteBuffer buffer1 = ByteBuffer.allocate(8);
        ByteBuffer buffer2 = ByteBuffer.allocate(8);
        // 填充数据
        buffer1.put("first".getBytes());
        buffer1.flip();
        buffer2.put("second".getBytes());
        buffer2.flip();
        ByteBuffer[] byteBuffer = {buffer1, buffer2};
        // 多个Buffer写入1个channel
        outChannel.write(byteBuffer);

    }

    @Test
    public void copy() throws IOException{
        // - transferForm(srcChannle,position,channelSize)
        FileChannel inChannel = new FileInputStream("D:\\a.jpg").getChannel();
        FileChannel outChannel = new FileOutputStream("D:\\workspace2\\java48th\\copy_a.jpg").getChannel();
        //outChannel.transferFrom(inChannel, 0, inChannel.size());

        //- transferTo(position,channelSize,destChannel)
        inChannel.transferTo(0, inChannel.size(), outChannel);

    }

    @Test
    public void copy2() throws IOException {
        // 使用第三方的工具进行复制
        FileUtils.copyFile(new File("D:\\a.jpg"), new File("D:\\workspace2\\java48th\\copy_a.jpg"));

    }
}
